<?php
/*
 * Created on Mar 7, 2009
 *
 * author: David Palmer <blinder.dave@gmail.com>
 * Just a convienence class for re-usable tools
 * 
 */

class Tools {
	private $svars;
	
	public static function debug ($pretty=true, $object) {
		if (DEBUG) { 
			if ($pretty) {
				echo "<pre>";
			}
			print_r($object);
			if ($pretty) {
				echo "</pre>";
			}
		}
	}
	
	/**
	 * load class path takes a comma delimited list of class paths (where
	 * php classes live) and loads them. This is necessary because we cache
	 * object references, and if we use an object reference from the cache
	 * we need to know the class's definition first. So this function will
	 * be called for every request. It is not an expensive call to make. 
	 */
	 public static function loadClassPath($classpath) {
	 	$cp = explode(",",$classpath);
	 	
	 	foreach ($cp as $entry) {
	 		Tools::loadClass($entry);
	 	}
	 }
	
	/**
	 * Look for a cached object by its 'key'
	 * @return mixed/object
	 */
	public static function getCachedObject($key) {
		global $memcache;
		
		return $memcache->get($key);
		
	}
	
	/**
	 * Set an object in the cache, by supplying a key and
	 * the actual object to be cached
	 * 
	 * @return true or false
	 */
	public static function setCachedObject($key,$obj,$compress=MEMCACHE_COMPRESSED,$expire=0) {
		global $memcache;
		
		return $memcache->set($key,$obj,$compress,$expire);
	}
	
	public static function deleteCachedObject($key) {
		global $memcache;
		return $memcache->delete($key);
	}
	
	/**
	 * Clear our cache
	 * 
	 * @return void
	 */
	public static function flushCache() {
		global $memcache;
		
		return $memcache->flush();
	}
	
	public static function initCache() {
		$servers = explode(",",MEMCACHE_SERVERS);
		$memcache = new Memcache;
		foreach ($servers as $s) {
			list ($host,$port) = split(":",$s);
			$memcache->addServer($host,$port);
		}
		return $memcache;
	}
	
	public static function getSessionVars() {
		$svars = array();
		if (isset($_SESSION)) {
			foreach ($_SESSION as $k => $v) {
				if (! isset($svars[$k])) {
					$svars[$k]=$v;
				}
			}
		}
		return $svars;
	}
	
	public static function clearSession() {
		/*
		 * The following code was originally posted from:
		 * http://us2.php.net/manual/en/function.session-destroy.php
		 */
		// Unset all of the session variables.
		$_SESSION = array();

		// If it's desired to kill the session, also delete the session cookie.
		// Note: This will destroy the session, and not just the session data!
		if (isset($_COOKIE[session_name()])) {
    		@setcookie(session_name(), '', time()-42000, '/');
		}

		// Finally, destroy the session.
		session_destroy();
	}
	
	/**
	 * CODE SOURCE: http://us2.php.net/uniqid
	 * ORIGINAL AUTHOR: sean at seancolombo dot com
	 * 
     * @brief Generates a Universally Unique IDentifier, version 4.
     *
     * This function generates a truly random UUID. The built in CakePHP String::uuid() function
     * is not cryptographically secure. You should uses this function instead.
     *
     * @see http://tools.ietf.org/html/rfc4122#section-4.4
     * @see http://en.wikipedia.org/wiki/UUID
     * @return string A UUID, made up of 32 hex digits and 4 hyphens.
     */
     public static function uuidSecure() {
      
        $pr_bits = null;
        $fp = @fopen('/dev/urandom','rb');
        if ($fp !== false) {
            $pr_bits .= @fread($fp, 16);
            @fclose($fp);
        } else {
            // If /dev/urandom isn't available (eg: in non-unix systems), use mt_rand().
            $pr_bits = "";
            for($cnt=0; $cnt < 16; $cnt++){
                $pr_bits .= chr(mt_rand(0, 255));
            }
        }
      
        $time_low = bin2hex(substr($pr_bits,0, 4));
        $time_mid = bin2hex(substr($pr_bits,4, 2));
        $time_hi_and_version = bin2hex(substr($pr_bits,6, 2));
        $clock_seq_hi_and_reserved = bin2hex(substr($pr_bits,8, 2));
        $node = bin2hex(substr($pr_bits,10, 6));
      
        /**
         * Set the four most significant bits (bits 12 through 15) of the
         * time_hi_and_version field to the 4-bit version number from
         * Section 4.1.3.
         * @see http://tools.ietf.org/html/rfc4122#section-4.1.3
         */
        $time_hi_and_version = hexdec($time_hi_and_version);
        $time_hi_and_version = $time_hi_and_version >> 4;
        $time_hi_and_version = $time_hi_and_version | 0x4000;
      
        /**
         * Set the two most significant bits (bits 6 and 7) of the
         * clock_seq_hi_and_reserved to zero and one, respectively.
         */
        $clock_seq_hi_and_reserved = hexdec($clock_seq_hi_and_reserved);
        $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved >> 2;
        $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved | 0x8000;
      
        return sprintf('%08s-%04s-%04x-%04x-%012s',
            $time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $node);
    } 
	
	/**
	 * Private function to recusively load php classes based on a path we provide
	 * Code originally adapted from: http://codingforums.com/showthread.php?t=71882
	 * author: 'missing-score'
	 */
	private static function loadClass( $path, $level = 0 ) {
		$dh = @opendir( $path );
		
		// Open the directory to the handle $dh
		while ( false !== ( $file = readdir( $dh ) ) ) {
			// Loop through the directory
			if (preg_match("/^\./",$file) == 0) { 
				if ( is_dir( "$path/$file" ) ) {
					// Its a directory, so we need to keep reading down...
					Tools::loadClass( "$path/$file", ($level+1) );
					// Re-call this same function but on a new directory.
					// this is what makes function recursive.
				} else {
					require_once($path . "/" . $file);
				}
			}
		}
		
		closedir( $dh );
		// Close the directory handle
	}
	
	public static function getDoParameter($do) {
		if (preg_match("/^\/[a-z]{2}\/(.*)$/",$do)) { 
			$action = substr($do,3,strlen($do)); // get the actual action in uri that looks like: /en/login
			if ($action =="") {
				$action="_default_";
			}
		} else {
			if ($do == "/" || $do == "") { 
				$action = "_default_";
			} else {
				$action = $do;
			}
		}
		return $action;
	}
	
	//resolve a relative url to something the browser can use (absolute or rooted at /)
	public static function resolveUri($uri){
		global $appConfig;
		if(strpos($uri,"://")==FALSE){
			//relative URL
			if($uri[0]=="/"){
				return $uri;
			}else{
				return "/" . $appConfig->getCurrentLanguage() . "/" . $uri;
			}
		}else{
			//absolute URL
			return $uri;
		}
	}
}
/**
 * this may look ugly but its quite simple really. we want to define our own import function
 * so that we can use our custom "class loading" mechanism
 */ 
function import($class) {
	$class_path = str_replace(".", "/",$class) . ".php";
	include_once(CLASSPATH."/" . $class_path);
}
?>